需求描述:类一旦初始化后,禁止更新变量值,且只能初始化一次(单例)。

定义装饰器 readOnlyProperties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def readOnlyProperties(*attrs):
"""
变量只读
"""
def class_rebuilder(cls):
"""The class decorator example"""
class NewClass(cls):
"""This is the overwritten class"""
def __setattr__(self, name, value):

if name not in attrs:
pass
elif name not in self.__dict__:
pass
else:
raise AttributeError("Can't touch {}".format(name))

super().__setattr__(name, value)

return NewClass

return class_rebuilder

定义Class : Singleton

1
2
3
4
5
6
7
8
9
class Singleton(type):
"""
单例模式
"""
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]

3.1定ass: Setting

class Setting 包含三个实例变量DEBUGMEDIA_PATH,LOG_PATH

1
2
3
4
5
6
@readOnlyProperties(['DEBUG','MEDIA_PATH','LOG_PATH'])
@dataclass
class Setting(object, metaclass=Singleton):
DEBUG: bool
MEDIA_PATH: str
LOG_PATH: str

input0

实例化2个不同实例s0,s1
更新s1.LOG_PATHs1.DEBUG

1
2
3
4
5
6
7
s0 = Setting(DEBUG=False, MEDIA_PATH='1', LOG_PATH='2')
s1 = UIAutoMeta(DEBUG=False, MEDIA_PATH='5', LOG_PATH='6')
print(s0)
s1.LOG_PATH='3'
s1.DEBUG=True
print(s0)
print(s1)

output0

禁止更新实例变量。

1
AttributeError: Can't update the key:LOG_PATH to value:3

input1

实例化2个不同实例s0,s1

1
2
3
4
5
6
7
s0 = Setting(DEBUG=False, MEDIA_PATH='1', LOG_PATH='2')
s1 = UIAutoMeta(DEBUG=False, MEDIA_PATH='5', LOG_PATH='6')
print(s0)
s1.LOG_PATH='3'
s1.DEBUG=True
print(s0)
print(s1)

output1

s1s2为同一个对象。

1
2
readOnlyProperties.<locals>.class_rebuilder.<locals>.NewClass(DEBUG=False, MEDIA_PATH='1', LOG_PATH='2')
readOnlyProperties.<locals>.class_rebuilder.<locals>.NewClass(DEBUG=False, MEDIA_PATH='1', LOG_PATH='2')

Python3.7版本

python3.7以后的版本可以这样写
定义一个dataclass,拥有nameage两个属性
实例化一个People,然后尝试对其age进行重新赋值。

1
2
3
4
5
6
7
8
9
10
11
from dataclasses import dataclass

@dataclass(frozen=True)
class People:
name: str
age: int


davida = People(name='davida', age=28)

davida.age = 29

输出

1
2
3
4
5
Traceback (most recent call last):
File "E:/workspaces/python/pytorchLearn/ttt.py", line 18, in <module>
davida.age = 29
File "<string>", line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'age'